package net.alan.modules.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import net.alan.common.constants.EProjectLogType;
import net.alan.common.constants.EJoinType;
import net.alan.common.constants.ENoticeType;
import net.alan.common.utils.Base64;
import net.alan.common.utils.CompareUtil;
import net.alan.common.utils.IOUtils;
import net.alan.common.utils.LangUtils;
import net.alan.modules.aspect.AdminRole;
import net.alan.modules.aspect.NotAuthorize;
import net.alan.modules.bean.*;
import net.alan.modules.cache.WebContextUtil;
import net.alan.modules.handle.BaseExecption;
import net.alan.modules.service.IProjectService;
import net.alan.modules.service.INoticeService;
import net.alan.modules.service.ITaskService;
import net.alan.modules.service.IUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Author 李岩飞
 * Email eliyanfei@126.com
 * 2017/11/21
 */
@Api(tags = "项目管理")
@Controller
@RequestMapping(value = "project")
public class ProjectController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(ProjectController.class);
    @Autowired
    private IUserService userService;
    @Autowired
    private IProjectService projectService;
    @Autowired
    private CustomConfig customConfig;
    @Autowired
    private INoticeService noticeService;
    @Autowired
    private ITaskService taskService;

    @NotAuthorize
    @RequestMapping(value = "join/{id}", method = RequestMethod.GET)
    public String join(@PathVariable("id") String id, Model model) {
        Integer projectId = LangUtils.toInt(Base64.decodeString(id), 0);
        Project project = projectService.getById(Project.class, projectId);
        if (!WebContextUtil.isLogin()) {
            model.addAttribute("msg", "还没有登录系统");
        } else if (project == null)
            model.addAttribute("msg", "项目不存在");
        else {
            EJoinType joinType = EJoinType.valueOf(project.getJoinTYpe());
            if (joinType == EJoinType.everybody) {
                projectService.joinProject(WebContextUtil.getUserId(), projectId);
                model.addAttribute("msg", "加入项目成功");
            } else if (joinType == EJoinType.somebody) {
                noticeService.addNotice(ENoticeType.invite.getName(), ENoticeType.invite, projectId, project.getUser().getId());
                model.addAttribute("msg", "加入项目申请已提交");
            }
        }
        return "web/project/join";
    }


    @ApiOperation(value = "添加项目", notes = "")
    @RequestMapping(value = "add", method = RequestMethod.POST)
    @ResponseBody
    public Result add(Project project) throws Exception {
        User user = WebContextUtil.getCurrentUser().getUser();
        project.setUser(user);
        if (project.getId() != null) {
            return projectService.editProject(project);
        }
        return projectService.addProject(project);
    }

    @ApiOperation(value = "移交项目", notes = "")
    @RequestMapping(value = "move", method = RequestMethod.POST)
    @ResponseBody
    public Result move(Integer id, Integer userId) throws Exception {
        return projectService.moveProject(id, userId);
    }

    @ApiOperation(value = "列表项目", notes = "")
    @RequestMapping(value = "list", method = RequestMethod.GET)
    @ResponseBody
    public List<Project> list(Integer projectId, PageModel pageModel) throws Exception {
        return projectService.findProjectByUserId(WebContextUtil.getUserId());
    }

    @ApiOperation(value = "项目用户", notes = "")
    @RequestMapping(value = "projectuser", method = RequestMethod.GET)
    @ResponseBody
    public List<UserProject> projectuser(Integer projectId) throws Exception {
        return userService.findUserProjectByProjectId(projectId);
    }

    @ApiOperation(value = "列表项目笔记", notes = "")
    @RequestMapping(value = "listnote", method = RequestMethod.GET)
    @ResponseBody
    public PageModel listnote(Integer projectId, PageModel pageModel) throws Exception {
        if (projectId == null)
            projectId = -1;
        Page<ProjectNote> page = projectService.findProjectNoteByProjectId(projectId, pageModel);
        return pageModel.toPageModel(page);
    }

    @ApiOperation(value = "列表项目附件", notes = "")
    @RequestMapping(value = "listattach", method = RequestMethod.GET)
    @ResponseBody
    public PageModel listattach(Integer projectId, PageModel pageModel) throws Exception {
        if (projectId == null)
            projectId = -1;
        Page<ProjectAttach> page = projectService.findProjectAttachByProjectId(projectId, pageModel);
        return pageModel.toPageModel(page);
    }

    @ApiOperation(value = "列表项目日志", notes = "")
    @RequestMapping(value = "listlog", method = RequestMethod.GET)
    @ResponseBody
    public PageModel listlog(Integer projectId, PageModel pageModel) throws Exception {
        if (projectId == null)
            projectId = -1;
        Page<ProjectLog> page = projectService.findProjectLogByProjectId(projectId, pageModel);
        return pageModel.toPageModel(page);
    }

    @ApiOperation(value = "列表")
    @RequestMapping(value = "listnotehistory/{id}", method = RequestMethod.GET)
    @ApiImplicitParam(name = "id", value = "Id", required = true, dataType = "Integer")
    @ResponseBody
    public PageModel listhistory(@PathVariable("id") Integer id, PageModel pageModel) throws Exception {
        Page<ProjectNoteHistory> list = null;
        list = this.projectService.findProjectNoteHistoryByNoteId(id, pageModel);
        return pageModel.toPageModel(list);
    }

    @ApiOperation(value = "获取单个历史笔记", notes = "")
    @ApiImplicitParam(name = "id", value = "Id", required = true, dataType = "Integer")
    @RequestMapping(value = "gethistory/{id}", method = RequestMethod.GET)
    @ResponseBody
    public ProjectNoteHistory gethistory(@PathVariable("id") Integer id) throws Exception {
        return projectService.getById(ProjectNoteHistory.class, id).copy();
    }

    @ApiOperation(value = "删除项目", notes = "")
    @ApiImplicitParam(name = "id", value = "组ID", required = true, dataType = "Integer")
    @RequestMapping(value = "delete/{id}", method = RequestMethod.POST)
    @ResponseBody
    public Result delete(@PathVariable("id") Integer id) throws Exception {
        return this.projectService.deleteProject(id);
    }

    @ApiOperation(value = "退出项目", notes = "")
    @RequestMapping(value = "quit", method = RequestMethod.POST)
    @ResponseBody
    public Result quit(Integer projectId) throws Exception {
        return this.userService.quitUserProject(projectId);
    }

    @ApiOperation(value = "从项目中删除成员", notes = "")
    @RequestMapping(value = "deleteuser", method = RequestMethod.POST)
    @ResponseBody
    public Result deleteuser(Integer projectId, Integer userId) throws Exception {
        return this.userService.deleteUserProject(projectId, userId);
    }

    @ApiOperation(value = "删除笔记", notes = "")
    @ApiImplicitParam(name = "id", value = "组ID", required = true, dataType = "Integer")
    @RequestMapping(value = "deletenote/{id}", method = RequestMethod.POST)
    @ResponseBody
    public Result deletenote(@PathVariable("id") Integer id) throws Exception {
        return this.projectService.deleteProjectNote(id);
    }

    @AdminRole
    @ApiOperation(value = "所有项目")
    @RequestMapping(value = "projectall", method = RequestMethod.GET)
    @ResponseBody
    public PageModel projectall(PageModel pageModel) throws Exception {
        Page page = projectService.findAll(Project.class, pageModel);
        return pageModel.toPageModel(page);
    }


    @ApiOperation(value = "获取一个项目")
    @ApiImplicitParam(name = "id", value = "组ID", required = true, dataType = "Integer")
    @RequestMapping(value = "get/{id}", method = RequestMethod.GET)
    @ResponseBody
    public Project get(@PathVariable Integer id) throws Exception {
        return projectService.getById(Project.class, id).copy();
    }

    @RequestMapping(value = "getstat/{id}", method = RequestMethod.GET)
    @ResponseBody
    public DataStat getstat(@PathVariable Integer id) throws Exception {
        DataStat dataStat = new DataStat();
        try {
            List<Object[]> list = taskService.statTask(id);
            if (list != null && list.size() > 0) {
                Object[] obj = list.get(0);
                dataStat.setL3((LangUtils.toInt(obj[1]) * 100 / LangUtils.toInt(obj[0])));
            }
        } catch (Exception e) {
            dataStat.setD3(0d);
        }
        return dataStat;
    }

    @RequestMapping(value = "getcompare", method = RequestMethod.GET)
    @ResponseBody
    public List<Object> getcompare(Integer id1, Integer id2) throws Exception {
        List<Object> list = new ArrayList();
        ProjectNote note = this.projectService.getById(ProjectNote.class, id1);
        ProjectNoteHistory noteHistory = this.projectService.getById(ProjectNoteHistory.class, id2);
        list.add(noteHistory.copy());
        note = note.copy();
        note.setContent(CompareUtil.compare(noteHistory.getContent(), note.getContent()));
        list.add(note);
        return list;
    }

    @ApiOperation(value = "获取单个笔记", notes = "")
    @ApiImplicitParam(name = "id", value = "Id", required = true, dataType = "Integer")
    @RequestMapping(value = "getnote/{id}", method = RequestMethod.GET)
    @ResponseBody
    public ProjectNote getnote(@PathVariable("id") Integer id) throws Exception {
        ProjectNote projectNote = projectService.getById(ProjectNote.class, id).copy();
        String mark = "<span class='insert' time='" + System.currentTimeMillis() + "' userid='" + WebContextUtil.getUserId() + "'/>";
        projectNote.setContent(projectNote.getContent() + mark);
        return projectNote.copy();
    }

    @ApiOperation(value = "添加", notes = "")
    @RequestMapping(value = "addnote", method = RequestMethod.POST)
    @ResponseBody
    public Result addnote(Integer id, String name, Integer projectId, String content) throws Exception {
        try {
            ProjectNote note = this.projectService.getById(ProjectNote.class, id);
            if (note == null) {
                note = new ProjectNote();
                note.setUserId(WebContextUtil.getUserId());
            }
            String ctt = note.getContent();
            note.setName(name);
            note.setContent(content);
            note.setProjectId(projectId);
            projectService.saveNote(ctt, note);
        } catch (Exception baseExecption) {
            return ResultUtil.error("保存异常");
        }
        return ResultUtil.success();
    }

    @RequestMapping(value = "downattach/{id}", method = RequestMethod.GET)
    @ResponseBody
    public void downattach(@PathVariable("id") Integer id, HttpServletResponse response) {
        response.setCharacterEncoding("utf-8");
        OutputStream os = null;
        try {
            os = response.getOutputStream();
            response.reset();
            response.setContentType("bin");
            ProjectAttach attach = projectService.getById(ProjectAttach.class, id);
            try {
                response.setHeader("Content-type", "text/csv; charset=utf-8");
                response.setHeader("Content-Disposition", "attachment; filename=\"" +  java.net.URLEncoder.encode(attach.getFileName(), "UTF-8") + "\"");
            } catch (Exception localUnsupportedEncodingException) {
            }
            String filePath = customConfig.getWorkPath() + attach.getName();
            IOUtils.copyStream(new File(filePath), os);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                os.flush();
            } catch (Exception e) {
            }
            IOUtils.closeIO(os);
        }
    }

    /**
     * 文件上传
     */
    @RequestMapping(value = "upload/file", method = RequestMethod.POST)
    @ResponseBody
    public Result uploadFile(Integer projectId, Integer taskId, HttpServletRequest request)
            throws Exception, IOException {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        try {
            String postFix =
                    IOUtils.getPostFix(file.getOriginalFilename());
            String filePath = projectId + File.separator + System.currentTimeMillis() + "." + postFix;
            IOUtils.copyStream(file.getInputStream(), customConfig.getWorkPath() + filePath);
            ProjectAttach projectAttach = new ProjectAttach();
            projectAttach.setFileName(file.getOriginalFilename());
            projectAttach.setUserId(WebContextUtil.getUserId());
            projectAttach.setName(filePath);
            projectAttach.setTaskId(taskId);
            projectAttach.setProjectId(projectId);
            projectService.save(ProjectAttach.class, projectAttach);
            projectService.addProjectLog(projectId, EProjectLogType.common, "上传资料-" + projectAttach.getFileName());
        } catch (BaseExecption baseExecption) {
            ResultUtil.error("");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResultUtil.success();
    }
}
